from fastapi import APIRouter, Depends, HTTPException, Request, Response
from fastapi.responses import RedirectResponse
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional
from datetime import datetime, timezone

from app.db.session import get_db
from app.db.crud import url as crud_url, click as crud_click
from app.schemas.shortener import URLCreate, URLResponse
from app.core.utils import generate_short_code, cache_url, get_cached_url, redis_client, check_code
from app.core.security import decode_jwt
from app.routes.auth import oauth2_scheme

router = APIRouter()

@router.post("/shorten", response_model=URLResponse)
async def create_short_url(
    url_in: URLCreate,
    db: AsyncSession = Depends(get_db),
    token: str = Depends(oauth2_scheme)
):
    # 从 token 中获取用户 ID
    user_data = decode_jwt(token)
    user_id = user_data.get("sub")  # "sub" 是用户 ID

    if not user_id:
        raise HTTPException(status_code=401, detail="Invalid token")

    short_code = generate_short_code(url_in)

    db_url = await crud_url.create(
        db,
        original_url=str(url_in.original_url),
        short_code=short_code,
        owner_id=user_id,  # 使用从 token 中获取的用户 ID
        expires_at=url_in.expires_at
    )
    
    # 缓存短链接
    expire_seconds = None
    if url_in.expires_at:
        current_time = datetime.now(timezone.utc)
        expires_at = url_in.expires_at.replace(tzinfo=timezone.utc)
        expire_seconds = int((expires_at - current_time).total_seconds())
    
    cache_url(short_code, str(url_in.original_url), expire_seconds)
    
    return db_url

@router.get("/{short_code}")
async def redirect_to_url(
    short_code: str,
    request: Request,
    db: AsyncSession = Depends(get_db)
):
    # 先从缓存获取
    original_url = get_cached_url(short_code)

    if not original_url:
        # 缓存未命中，从数据库获取
        db_url = await crud_url.get_by_short_code(db, short_code)
        if not db_url:
            raise HTTPException(status_code=404, detail="URL not found")
        original_url = db_url.original_url

        # 检查是否过期
        if db_url.expires_at and db_url.expires_at < datetime.now(timezone.utc):
            raise HTTPException(status_code=410, detail="URL has expired")

        # 重新缓存
        if db_url.expires_at:
            expire_seconds = int((db_url.expires_at.replace(tzinfo=timezone.utc) - datetime.now(timezone.utc)).total_seconds())
            if expire_seconds > 0:
                cache_url(short_code, original_url, expire_seconds)
        else:
            cache_url(short_code, original_url)

    # 记录点击
    await crud_click.create(
        db,
        url_id=db_url.id,
        ip_address=request.client.host,
        user_agent=request.headers.get("user-agent", "")
    )

    return RedirectResponse(url=original_url) 